using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using QFramework;
using Unity.VisualScripting;
using UnityEngine;
using XCZProject;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;

// 全局脚本
public class Global : Architecture<Global>
{
    #region Model
    public static BindableProperty<int> HP = new BindableProperty<int>(3);// 玩家当前血量
    public static BindableProperty<int> MaxHP = new BindableProperty<int>(3);// 玩家血量上限

    
    public static BindableProperty<int> Exp = new BindableProperty<int>(0);// 玩家当前经验
    public static BindableProperty<int> Coin = new BindableProperty<int>(0);// 玩家当前金币
    public static BindableProperty<int> Lv = new BindableProperty<int>(1);// 玩家当前等级，默认初始1级
    public static BindableProperty<float> CurrentSecond = new BindableProperty<float>(0);// 当前游戏时间，游戏界面中以00:00显示

    public static BindableProperty<bool> BombUnlocked = new BindableProperty<bool>(false);
    public static BindableProperty<float> BombDamage = new BindableProperty<float>(Config.InitBombDamage);
    public static BindableProperty<float> BombPercent = new BindableProperty<float>(Config.InitBombPercent);// 炸弹掉落概率
    
    public static BindableProperty<bool> SimpleSwordUnlocked = new BindableProperty<bool>(false);
    public static BindableProperty<float> SimpleAbilityDamage = new BindableProperty<float>(Config.InitSimpleSwordDamege);// 基础攻击力
    public static BindableProperty<float> SimpleAbilityDuration = new BindableProperty<float>(Config.InitSimpleSwordDuration);// 基础攻击频率
    public static BindableProperty<int> SimpleSwordCount = new BindableProperty<int>(Config.InitSimpleSwordCount);// 小刀数量
    public static BindableProperty<float> SimpleSwordRange = new BindableProperty<float>(Config.InitSimpleSwordRange);// 攻击范围
    
    public static BindableProperty<bool> SimpleKnifeUnlocked = new BindableProperty<bool>(false);
    public static BindableProperty<float> SimpleKnifeDamage = new BindableProperty<float>(Config.InitSimpleKnifeDamege);// 基础攻击力
    public static BindableProperty<float> SimpleKnifeDuration = new BindableProperty<float>(Config.InitSimpleKnifeDuration);// 基础攻击频率
    public static BindableProperty<int> SimpleKnifeCount = new BindableProperty<int>(Config.InitSimpleKnifeCount);// 小刀数量
    public static BindableProperty<int> SimpleKnifeAttackCount = new BindableProperty<int>(1);

    public static BindableProperty<bool> RotateSwordUnlocked = new BindableProperty<bool>(false);
    public static BindableProperty<float> RotateSwordDamage = new BindableProperty<float>(Config.InitRotateSwordDamage);
    public static BindableProperty<int> RotateSwordCount = new BindableProperty<int>(Config.InitRotateSwordCount);
    public static BindableProperty<float> RotateSwordSpeed = new BindableProperty<float>(Config.InitRotateSwordSpeed);
    public static BindableProperty<float> RotateSwordRange = new BindableProperty<float>(Config.InitRotateSwordRange);
    
    public static BindableProperty<bool> BasketBallUnlocked = new BindableProperty<bool>(false);
    public static BindableProperty<float> BasketBallDamage = new BindableProperty<float>(Config.InitBasketBallDamage);
    public static BindableProperty<float> BasketBallSpeed = new BindableProperty<float>(Config.InitBasketBallSpeed);
    public static BindableProperty<int> BasketBallCount = new BindableProperty<int>(Config.InitBasketBallCount);
    
    public static BindableProperty<float> CriticalRate = new BindableProperty<float>(Config.InitCriticalRate);//暴击率
    public static BindableProperty<float> DamageRate = new BindableProperty<float>(1);// 伤害加成
    public static BindableProperty<int> SimpleFlyCount = new BindableProperty<int>(0);//飞行物数量，所有武器的数量

    public static BindableProperty<float> MovementSpeedRate = new BindableProperty<float>(1.0f);// 角色移动速度加成
    public static BindableProperty<float> CollectableArea = new BindableProperty<float>(0.5f);// 角色拾取范围
    public static BindableProperty<float> AdditonalExpPercent = new BindableProperty<float>(0);// 经验值掉落概率加成

    public static BindableProperty<bool> SuperKnife = new BindableProperty<bool>(false);
    public static BindableProperty<bool> SuperSword = new BindableProperty<bool>(false);
    public static BindableProperty<bool> SuperRotateSword = new BindableProperty<bool>(false);
    public static BindableProperty<bool> SuperBomb = new BindableProperty<bool>(false);
    public static BindableProperty<bool> SuperBasketBall = new BindableProperty<bool>(false);
    
    public static BindableProperty<float> ExpPercent = new BindableProperty<float>(0.3f);// 经验球掉落概率
    
    public static BindableProperty<float> CoinPercent = new BindableProperty<float>(0.05f);// 金币掉落概率

    #endregion
    
    /// <summary>
    /// 允许在运行时加载游戏时不通过用户操作 初始化一个运行时类方法。
    /// 游戏加载后，将调用标记为 [RuntimeInitializeOnLoadMethod] 的 方法。这是在调用 Awake 方法后进行的。
    /// </summary>
    [RuntimeInitializeOnLoadMethod]
    public static void AutoInit()
    {
        // 音效设置，避免大量怪物被炸死时音效重复，现在的设置是在10帧内的同音效不会重复播放
        AudioKit.PlaySoundMode = AudioKit.PlaySoundModes.IgnoreSameSoundInGlobalFrames;
        // 初始化资源加载器
        ResKit.Init();
        
        // 读取角色最大血量
        Global.MaxHP.Value = PlayerPrefs.GetInt(nameof(MaxHP), 3);
        HP.Value = MaxHP.Value;
        
        // 设置UI的分辨率
        UIKit.Root.SetResolution(1920,1080,1);
        
        // 读取金币数量、经验值掉落概率、金币掉落概率等存档数值
        Coin.Value = PlayerPrefs.GetInt("coin", 0);
        Global.ExpPercent.Value = PlayerPrefs.GetFloat(nameof(ExpPercent),0.3f);
        Global.CoinPercent.Value = PlayerPrefs.GetFloat(nameof(CoinPercent),0.05f);
        
        // 注册金币变化事件
        Global.Coin.Register(coin =>
        {
            PlayerPrefs.SetInt(nameof(coin), coin);
        });
        
        // 注册经验值掉落概率变化事件
        Global.ExpPercent.Register(expPerent =>
        {
            PlayerPrefs.SetFloat(nameof(expPerent), expPerent);
        });
        
        // 注册金币掉落概率改变事件
        Global.CoinPercent.Register(coinPerent =>
        {
            PlayerPrefs.SetFloat(nameof(coinPerent), coinPerent);
        });
        
        // 注册最大血量改变事件
        Global.MaxHP.Register(maxhp =>
        {
            PlayerPrefs.SetInt(nameof(MaxHP), maxhp);
        });

    }

    /// <summary>
    /// 重置游戏数据，一般是当游戏结束或游戏通关，重新开始时调用
    /// </summary>
    public static void ResetDate()
    {
        HP.Value = MaxHP.Value;
        Exp.Value = 0;
        Lv.Value = 1;
        CurrentSecond.Value = 0;

        SimpleSwordUnlocked.Value = false;
        SimpleAbilityDamage.Value = Config.InitSimpleSwordDamege;
        SimpleAbilityDuration.Value = Config.InitSimpleSwordDuration;
        SimpleSwordCount.Value = Config.InitSimpleSwordCount;
        SimpleSwordRange.Value = Config.InitSimpleSwordRange;

        SimpleKnifeUnlocked.Value = false;
        SimpleKnifeDamage.Value = Config.InitSimpleKnifeDamege;
        SimpleKnifeDuration.Value = Config.InitSimpleKnifeDuration;
        SimpleKnifeCount.Value = Config.InitSimpleKnifeCount;
        SimpleKnifeAttackCount.Value = 1;

        RotateSwordUnlocked.Value = false;
        RotateSwordDamage.Value = Config.InitRotateSwordDamage;
        RotateSwordCount.Value = Config.InitRotateSwordCount;
        RotateSwordSpeed.Value = Config.InitRotateSwordSpeed;
        RotateSwordRange.Value = Config.InitRotateSwordRange;

        BasketBallUnlocked.Value = false;
        BasketBallDamage.Value = Config.InitBasketBallDamage;
        BasketBallCount.Value = Config.InitBasketBallCount;
        BasketBallSpeed.Value = Config.InitBasketBallSpeed;

        BombUnlocked.Value = false;
        BombDamage.Value = Config.InitBombDamage;
        BombPercent.Value = Config.InitBombPercent;
        
        CriticalRate.Value = Config.InitCriticalRate;
        CollectableArea.Value = Config.InitCollectableArea;
        AdditonalExpPercent.Value=0;
        
        SimpleFlyCount.Value = 0;
        DamageRate.Value = 1;
        MovementSpeedRate.Value = 1.0f;

        SuperKnife.Value = false;
        SuperBasketBall.Value = false;
        SuperRotateSword.Value = false;
        SuperBomb.Value = false;
        SuperSword.Value = false;
        
        EnemyGenerator.EnemyCount.Value = 0;
        
        // Interface代表自己的单例，下面是获取经验升级系统，并且重置数据
        Interface.GetSystem<ExpUpgradeSystem>().ResetData();
    }

    /// <summary>
    /// 升级到下个等级需要的经验值
    /// </summary>
    /// <returns></returns>
    public static int ExpToNextLevel()
    {
        return Lv.Value * 5;
    }

    /// <summary>
    /// 生成掉落奖励
    /// </summary>
    /// <param name="gameObject">传入的GameObject主要用于确认生成坐标</param>
    public static void GeneratePowerUp(GameObject gameObject,bool treasureChestEnemy)
    {
        //print("开始掉落经验球");
        // 是否掉落宝箱
        if (treasureChestEnemy)
        {
            PowerUpManager.Default.TreasureChest
                .Instantiate()
                .Position(gameObject.Position())
                .Show();
            return;
        }
        
        // 根据概率掉落经验值和金币，掉落概率可以在主界面进行升级
        var random = Random.Range(0, 1.0f);
        if (random<=ExpPercent.Value+AdditonalExpPercent.Value)
        {
            // 掉落经验值
            PowerUpManager.Default.Exp.Instantiate()
                .Position(gameObject.Position())
                .Show();
            return;
        }
        random = Random.Range(0, 1.0f);
        if (random<=ExpPercent.Value)
        {
            // 掉落金币
            PowerUpManager.Default.Coin.Instantiate()
                .Position(gameObject.Position())
                .Show();
            return;
        }
        
        random = Random.Range(0, 1.0f);
        // 如果随机到且场景中没有血球，则生成血球
        if (random<=0.1f&&!UnityEngine.Object.FindObjectOfType<Hp>())
        {
            // 掉落血球
            PowerUpManager.Default.Hp.Instantiate()
                .Position(gameObject.Position())
                .Show();
            return;
        }

        // 当炸弹解锁，且场景内没有炸弹的时候，才会有概率生成炸弹
        if (BombUnlocked.Value&&!Object.FindObjectOfType<Bomb>())
        {
            random = Random.Range(0, 1.0f);
            if (random<=BombPercent.Value)
            {
                // 掉落炸弹
                PowerUpManager.Default.Bomb.Instantiate()
                    .Position(gameObject.Position())
                    .Show();
                return;
            }
        }
        
        random = Random.Range(0, 1.0f);
        if (random<=0.1f)
        {
            // 掉落全部拾取经验的道具
            PowerUpManager.Default.GetAllExp.Instantiate()
                .Position(gameObject.Position())
                .Show();
            return;
        }

        //var _ = Interface;
    }

    protected override void Init()
    {
        Debug.Log("开始注册系统");
        // 进行一些注册操作
        this.RegisterSystem(new CoinUpgradeSystem());
        this.RegisterSystem(new SaveSystem());
        this.RegisterSystem(new ConfigSystem());
        this.RegisterSystem(new ExpUpgradeSystem());
        
        // 重置数据
        // var ceshi = this.GetSystem<SaveSystem>();
        // ceshi.SaveBool("coin_percent_lv1",false);
        // ceshi.SaveBool("coin_percent_lv2",false);
        // ceshi.SaveBool("coin_percent_lv3",false);
        // ceshi.SaveBool("exp_percent",false);
    }
}
